from functools import wraps
import traceback
import logging as log
from settings import DEBUG, ADMIN_NAME
from utils.token import token_decode
from utils.format import pretty_data
from errors import TokenError
from db import UsersTB
from sanic.response import json as res_json


class cached_property(object):
    """此装饰器类似property，不过所装饰的属性带有缓存，属性代码只执行一回"""

    def __init__(self, func):
        self.func = func
        self.__doc__ = getattr(func, "__doc__")
        self.name = func.__name__

    def __get__(self, instance, cls=None):
        if instance is None:
            return self
        res = instance.__dict__[self.name] = self.func(instance)
        return res


def response_json(wrapped):
    def decorator(f):
        @wraps(f)
        async def decorated_function(request, *args, **kwargs):
            try:
                res = await f(request, *args, **kwargs)
                return res_json(dict(status=1, msg="success", dataset=pretty_data(res)))
            except Exception as e:
                log.error(traceback.format_exc())
                print(traceback.format_exc())
                return res_json(dict(status=0, msg=str(e), dataset={}))
        return decorated_function
    return decorator(wrapped)


def token_required_with_response(wrapped):
    def decorator(f):
        @wraps(f)
        async def decorated_function(request, *args, **kwargs):
            try:
                token = request.headers.get("token", None)
                if not token:
                    if DEBUG:
                        data = {"name": ADMIN_NAME}
                    else:
                        raise TokenError("无效token")
                else:
                    data = token_decode(token)
                user = UsersTB.get(username=data["name"])
                res = await f(request, user, *args, **kwargs)
                return res_json(dict(status=1, msg="success", dataset=pretty_data(res)))
            except TokenError:
                log.error(traceback.format_exc())
                print(traceback.format_exc())
                return res_json(dict(status=2, msg="无效token或登录过期", dataset={}))
            except Exception as e:
                log.error(traceback.format_exc())
                print(traceback.format_exc())
                return res_json(dict(status=0, msg=str(e), dataset={}))
        return decorated_function
    return decorator(wrapped)


